package com.thfw.test.utils;


import androidx.annotation.NonNull;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author litingwei
 * @date 2019/11/14.
 */
public class ThreadPoolManager {

    private static final int MAX_COMMON_POOL_SIZE = 5;
    private static final int MAX_PAGE_DATA_LOAD_POOL_SIZE = 2;

    private final ExecutorService commonExecutor;
    private final ExecutorService pageDataLoadExecutor;
    private final ScheduledExecutorService scheduleExecutor;
    private final ScheduledExecutorService timerScheduleExecutor;
    private final ExecutorService logExecutor;

    private static class ThreadPoolManagerHelper {
        private static ThreadPoolManager INSTANCE = new ThreadPoolManager();
    }

    private ThreadPoolManager() {
        commonExecutor = new ThreadPoolExecutor(1, MAX_COMMON_POOL_SIZE,
                60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadPoolFactory("common"));
        pageDataLoadExecutor = new ThreadPoolExecutor(1, MAX_PAGE_DATA_LOAD_POOL_SIZE,
                60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadPoolFactory("data"));
        scheduleExecutor = new ScheduledThreadPoolExecutor(1, new ThreadPoolFactory("scheduled"));
        timerScheduleExecutor = new ScheduledThreadPoolExecutor(1, new ThreadPoolFactory("time-scheduled"));
        logExecutor = new ThreadPoolExecutor(1, 1,
                60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadPoolFactory("log"));
    }

    public static ThreadPoolManager getInstance() {
        return ThreadPoolManagerHelper.INSTANCE;
    }

    public ExecutorService getCommonExecutor() {
        return commonExecutor;
    }

    public ExecutorService getPageDataLoadExecutor() {
        return pageDataLoadExecutor;
    }

    public ScheduledExecutorService getScheduleExecutor() {
        return scheduleExecutor;
    }

    public ScheduledExecutorService getTimerScheduleExecutor() {
        return timerScheduleExecutor;
    }

    public ExecutorService getLogExecutor() {
        return logExecutor;
    }

    private static class ThreadPoolFactory implements ThreadFactory {

        private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        ThreadPoolFactory(String type) {
            SecurityManager s = System.getSecurityManager();
            group = s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            namePrefix = "pool-manager-" + type + "-p_" + POOL_NUMBER.getAndIncrement() + "-t_";
        }

        @Override
        public Thread newThread(@NonNull Runnable r) {
            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            return t;
        }
    }
}
